package com.booking.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.booking.common.dto.PageReq;
import com.booking.common.dto.PageResp;
import com.booking.common.enums.BookingErrorCode;
import com.booking.common.exception.BookingException;
import com.booking.common.utils.ConvertUtils;
import com.booking.common.utils.DtUtils;
import com.booking.common.utils.LocalDateTimeUtils;
import com.booking.controller.model.req.homestay.HomestayCreateReq;
import com.booking.controller.model.req.homestay.HomestayQueryReq;
import com.booking.controller.model.req.homestay.HomestayRoomCreateReq;
import com.booking.controller.model.req.homestay.HomestayServiceCreateReq;
import com.booking.controller.model.res.HomestayDetail;
import com.booking.controller.model.res.HomestaySimpleInfo;
import com.booking.controller.model.res.RoomDetail;
import com.booking.controller.model.res.ServiceDetail;
import com.booking.dao.dto.ScoreDTO;
import com.booking.dao.entity.HomestayInfo;
import com.booking.dao.entity.RoomInfo;
import com.booking.dao.entity.RoomOrder;
import com.booking.dao.entity.ServiceInfo;
import com.booking.dao.entity.ServiceOrder;
import com.booking.dao.service.HomestayInfoService;
import com.booking.dao.service.RoomCommentDetailService;
import com.booking.dao.service.RoomInfoService;
import com.booking.dao.service.RoomOrderService;
import com.booking.dao.service.ServiceCommentDetailService;
import com.booking.dao.service.ServiceInfoService;
import com.booking.dao.service.ServiceOrderService;
import com.booking.enums.OrderStatusEnums;
import com.booking.service.HomestayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Qikai.Lin
 * @date 2023/4/24
 */
@Slf4j
@Service
public class HomestayServiceImpl implements HomestayService {
    @Autowired
    private HomestayInfoService homestayInfoService;
    @Autowired
    private RoomInfoService roomInfoService;
    @Autowired
    private ServiceInfoService serviceInfoService;
    @Autowired
    private RoomOrderService roomOrderService;
    @Autowired
    private ServiceOrderService serviceOrderService;

    @Autowired
    private RoomCommentDetailService roomCommentDetailService;
    @Autowired
    private ServiceCommentDetailService serviceCommentDetailService;

    private HomestayInfo getHomestayInfo(Long homestayId) {
        HomestayInfo homestayInfo = homestayInfoService.getById(homestayId);
        if (homestayInfo == null) {
            throw new BookingException(BookingErrorCode.HOMESTAY_NOT_EXIST);
        }
        return homestayInfo;
    }

    private RoomInfo getRoomInfo(Long roomId) {
        RoomInfo roomInfo = roomInfoService.getById(roomId);
        if (roomInfo == null) {
            throw new BookingException(BookingErrorCode.ROOM_NOT_EXIST);
        }
        return roomInfo;
    }

    private ServiceInfo getServiceInfo(Long serviceId) {
        ServiceInfo serviceInfo = serviceInfoService.getById(serviceId);
        if (serviceInfo == null) {
            throw new BookingException(BookingErrorCode.SERVICE_NOT_EXIST);
        }
        return serviceInfo;
    }

    @Override
    public PageResp<HomestaySimpleInfo> getHomestaySimpleInfoPage(PageReq<HomestayQueryReq> request) {
        // 查询民宿基础信息
        PageResp<HomestayInfo> page = homestayInfoService.getPage(request);

        // 返回值
        PageResp<HomestaySimpleInfo> simplePage = new PageResp<>();
        ConvertUtils.copy(simplePage, page);
        List<HomestaySimpleInfo> simpleList = new ArrayList<>();
        page.getRecords().forEach(homestayInfo -> {
            HomestaySimpleInfo simpleInfo = ConvertUtils.convert(HomestaySimpleInfo.class, homestayInfo);
            // 查询民宿评价，计算评分
            ScoreDTO roomScoreDTO = roomCommentDetailService.getScoreDTOByHomestayId(homestayInfo.getId());
            if (roomScoreDTO.getSumScore() == null) roomScoreDTO.setSumScore(BigDecimal.ZERO);

            ScoreDTO serviceScoreDTO = serviceCommentDetailService.getScoreDTOByHomestayId(homestayInfo.getId());
            if (serviceScoreDTO.getSumScore() == null) serviceScoreDTO.setSumScore(BigDecimal.ZERO);

            BigDecimal homestayScore;
            if (roomScoreDTO.getCount() == 0 && serviceScoreDTO.getCount() == 0) {
                homestayScore = BigDecimal.ZERO;
            } else {
                homestayScore = roomScoreDTO.getSumScore()
                        .add(serviceScoreDTO.getSumScore())
                        .divide(BigDecimal.valueOf(roomScoreDTO.getCount()+serviceScoreDTO.getCount()),
                                2, RoundingMode.UP);
            }
            simpleInfo.setScore(homestayScore.multiply(new BigDecimal(2)).doubleValue());
            simpleList.add(simpleInfo);
        });
        // 按更新时间排序
        // 根据评分排序
        List<HomestaySimpleInfo> collect = simpleList.stream()
                .sorted(Comparator.comparing(HomestaySimpleInfo::getScore).thenComparing(HomestaySimpleInfo::getUpdatedTime))
                .collect(Collectors.toList());
        Collections.reverse(collect);
        simplePage.setRecords(collect);

        return simplePage;
    }
    @Override
    public HomestayDetail getHomestayDetail(Long homestayId) {
        log.info("民宿详情查询 homestayId={}", homestayId);
        // 查询民宿
        HomestayInfo homestayInfo = getHomestayInfo(homestayId);
        HomestayDetail homestayDetail = ConvertUtils.convert(HomestayDetail.class, homestayInfo);
        homestayDetail.setOpenDate(LocalDateTimeUtils.toYyyyMMddStr(homestayInfo.getOpenDate()));
        homestayDetail.setDecorateDate(LocalDateTimeUtils.toYyyyMMddStr(homestayInfo.getDecorateDate()));

        // 查询房间信息
        List<RoomInfo> roomInfoList = roomInfoService.getListByHomestayId(homestayId);
        homestayDetail.setRoomInfoList(roomInfoList);
        // 查询服务信息
        List<ServiceInfo> serviceInfoList = serviceInfoService.getByHomestayId(homestayId);
        homestayDetail.setServiceInfoList(serviceInfoList);

        // 更新民宿查询时间
        homestayInfo.setUpdatedTime(LocalDateTime.now());
        homestayInfoService.updateById(homestayInfo);
        log.info("民宿详情查询成功！ homestayDetail={}", JSON.toJSONString(homestayDetail));
        return homestayDetail;
    }
    @Override
    public String create(HomestayCreateReq request) {
        log.info("民宿创建 request={}", JSON.toJSONString(request));
        HomestayInfo homestayInfo = ConvertUtils.convert(HomestayInfo.class, request);
        homestayInfo.setId(IdWorker.getId());
        homestayInfo.setOwnerId(request.getUserId());
        homestayInfo.setOpenDate(LocalDateTimeUtils.yyyyMMddStrToLocalDateTime(request.getOpenDate()));
        homestayInfo.setDecorateDate(LocalDateTimeUtils.yyyyMMddStrToLocalDateTime(request.getDecorateDate()));
        homestayInfoService.save(homestayInfo);
        log.info("民宿创建成功！ homestayInfo={}", JSON.toJSONString(homestayInfo));
        return homestayInfo.getId().toString();
    }

    @Override
    public void delete(Long homestayId) {
        log.info("民宿删除 homestayId={}", homestayId);
        homestayInfoService.removeById(homestayId);
        log.info("民宿删除成功 homestayId={}", homestayId);
    }

    @Override
    public RoomDetail getRoomDetail(Long roomId) {
        log.info("房间详情查询 roomId={}", roomId);
        // 查询基本信息
        RoomInfo roomInfo = getRoomInfo(roomId);
        RoomDetail roomDetail = ConvertUtils.convert(RoomDetail.class, roomInfo);
        // 查询民宿信息
        HomestayInfo homestayInfo = getHomestayInfo(roomDetail.getHomestayId());
        roomDetail.setHomestayName(homestayInfo.getName());
        // 查询订单信息
        List<RoomOrder> roomOrders = roomOrderService.getListByRoomId(roomId);
        // 过滤掉END状态的订单
        List<RoomOrder> bookingOrders = roomOrders.stream()
                .filter(order -> !Objects.equals(order.getOrderStatus(), OrderStatusEnums.END.getStatus()))
                .collect(Collectors.toList());
        Set<String> bookingRoomDateSet = new HashSet<>();
        bookingOrders.forEach(order -> {
            bookingRoomDateSet.add(DtUtils.getDtStr(order.getCheckInDate()) + " 至 " + DtUtils.getDtStr(order.getCheckOutDate()) + " , ");
        });
        StringBuilder bookedDateList = new StringBuilder();
        bookingRoomDateSet.forEach(bookedDateList::append);
        if (bookedDateList.indexOf(",") >= 0) {
            bookedDateList.deleteCharAt(bookedDateList.lastIndexOf(","));
        }
        roomDetail.setBookedDateList(bookedDateList.toString());
        log.info("房间详情查询成功！ roomDetail={}", JSON.toJSONString(roomDetail));
        return roomDetail;
    }

    @Override
    public String createRoom(HomestayRoomCreateReq request) {
        log.info("民宿房间创建 request={}", JSON.toJSONString(request));
        // 查询民宿
        HomestayInfo homestayInfo = getHomestayInfo(Long.parseLong(request.getHomestayId()));

        RoomInfo roomInfo = ConvertUtils.convert(RoomInfo.class, request);
        roomInfo.setId(IdWorker.getId());
        roomInfo.setHomestayId(homestayInfo.getId());
        roomInfoService.save(roomInfo);
        log.info("民宿房间创建成功！ roomInfo={}", JSON.toJSONString(roomInfo));
        return roomInfo.getId().toString();
    }

    @Override
    public void deleteRoom(Long roomId) {
        log.info("房间删除 roomId={}", roomId);
        roomInfoService.removeById(roomId);
        log.info("房间删除成功 roomId={}", roomId);
    }

    @Override
    public ServiceDetail getServiceDetail(Long serviceId) {
        log.info("服务详情查询 serviceId={}", serviceId);
        // 查询服务信息
        ServiceInfo serviceInfo = getServiceInfo(serviceId);
        ServiceDetail serviceDetail = ConvertUtils.convert(ServiceDetail.class, serviceInfo);

        // 查询民宿信息
        HomestayInfo homestayInfo = getHomestayInfo(serviceDetail.getHomestayId());
        serviceDetail.setHomestayName(homestayInfo.getName());

        // 查询订单信息
        List<ServiceOrder> serviceOrders = serviceOrderService.getListByServiceId(serviceId);
        // 过滤掉END和SHUT_DOWN状态的订单
        List<ServiceOrder> bookingOrders = serviceOrders.stream()
                .filter(order -> !Objects.equals(order.getOrderStatus(), OrderStatusEnums.END.getStatus()))
                .collect(Collectors.toList());
        Set<String> bookingServiceDateSet = new HashSet<>();
        bookingOrders.forEach(order -> {
            bookingServiceDateSet.add(DtUtils.getDtStr(order.getServiceDate()) + ", ");
        });
        StringBuilder bookedDateList = new StringBuilder();
        bookingServiceDateSet.forEach(bookedDateList::append);
        if (bookedDateList.indexOf(",") >= 0) {
            bookedDateList.deleteCharAt(bookedDateList.lastIndexOf(","));
        }
        serviceDetail.setBookedDateList(bookedDateList.toString());
        log.info("服务详情查询成功！ serviceDetail={}", JSON.toJSONString(serviceDetail));
        return serviceDetail;
    }

    @Override
    public String createService(HomestayServiceCreateReq request) {
        log.info("民宿服务创建 request={}", JSON.toJSONString(request));
        // 查询民宿
        HomestayInfo homestayInfo = getHomestayInfo(request.getHomestayId());
        ServiceInfo serviceInfo = ConvertUtils.convert(ServiceInfo.class, request);
        serviceInfo.setId(IdWorker.getId());
        serviceInfo.setHomestayId(homestayInfo.getId());
        serviceInfo.setTagList("民宿");
        serviceInfoService.save(serviceInfo);
        log.info("民宿服务创建成功！ serviceInfo={}", JSON.toJSONString(serviceInfo));
        return serviceInfo.getId().toString();
    }

    @Override
    public void deleteService(Long serviceId) {
        log.info("服务删除 serviceId={}", serviceId);
        serviceInfoService.removeById(serviceId);
        log.info("服务删除成功 serviceId={}", serviceId);
    }

}
